package com.jsd.openapi.rest;


import com.alibaba.fastjson2.JSONObject;
import com.jsd.openapi.handler.RsaEncryptDecryptHandler;
import com.jsd.openapi.handler.RsaSignatureHandler;
import com.jsd.openapi.handler.SignatureHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.time.Instant;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * @author xm
 * @date 2024/1/21
 **/
@Slf4j
@Component
public class JsdRestUtil {
    @Value("${jsd.gateway_url}")
    public String GATEWAY_URL;
    /**
     * 请求模板
     */
    private final static RestTemplate REST_TEMPLATE = new RestTemplate();
    /**
     * 签名处理器
     */
    private final static SignatureHandler SIGNATURE_HANDLER = new RsaSignatureHandler();
    /**
     * 加密解密处理器
     */
    private final static RsaEncryptDecryptHandler RSA_ENCRYPT_DECRYPT_HANDLER = new RsaEncryptDecryptHandler();

    @Value("${jsd.mc_no}")
    public String mc_no;
    @Value("${jsd.mch_private}")
    public String mch_private;
    @Value("${jsd.platform_common}")
    public String platform_common;

    /**
     * 请求体传参，入参是json对象
     * 接口入参内容类型application/json
     */
    public JSONObject post(Map<String, Object> requestMap, String api) {
        //1.构造map格式入参
        // 原请求参数已经是map，这里不需要构造
        log.info("调用金舜达开放API原业务请求参数：{}", JSONObject.toJSONString(requestMap));

        //2.对参数签名
        String signature = SIGNATURE_HANDLER.sign(requestMap, mch_private);
        log.info("调用金舜达开放API原业务请求参数加签：{}", signature);

        //3.对原请求参数加密
//        String encText = RSA_ENCRYPT_DECRYPT_HANDLER.encryptByPublicKey(requestMap, platform_common);

        //4.构造网关请求入参
        Map<String, Object> secureRequestMap = new HashMap<>();
        secureRequestMap.put("mcNo", mc_no);
        secureRequestMap.put("timestamp", Instant.now().getEpochSecond());
        secureRequestMap.put("data", JSONObject.toJSONString(requestMap));
        secureRequestMap.put("reqId", UUID.randomUUID().toString());
        secureRequestMap.put("sign", signature);
        log.info("调用金舜达开放API网关请求URL：{}", GATEWAY_URL + api);
        log.info("调用金舜达开放API网关请求参数：{}", JSONObject.toJSONString(secureRequestMap));
        // 设置请求头为json
        HttpHeaders header = new HttpHeaders();
        header.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<Map<String, Object>> httpEntity = new HttpEntity<>(secureRequestMap, header);
        ResponseEntity<String> response = REST_TEMPLATE.postForEntity(GATEWAY_URL + api,
                httpEntity, String.class);
        String responseBody = response.getBody();
        log.info("请求http响应：{}", responseBody);
        if (responseBody == null) {
            // todo 网络未知错误时处理
            throw new RuntimeException(response.getStatusCode().toString());
        }

        JSONObject jsonObject = JSONObject.parseObject(responseBody);
        if (!"Y000".equals(jsonObject.getString("code"))) {
            // todo 这是网关非成功的返回，做一些逻辑处理，具体状态码可查看文档
            throw new RuntimeException(jsonObject.getString("msg"));
        } else {
            //5.业务内容解密
            String data = jsonObject.getString("data");
            if (data != null) {
//                log.info("调用金舜达开放API响应原始data：{}", data);
//                data = RSA_ENCRYPT_DECRYPT_HANDLER.decryptByPrivateKey(data, mch_private);
//                log.info("调用金舜达开放API响应解密data：{}", data);
//                jsonObject.put("data", data);

                // 6.验签
                String sign = jsonObject.getString("sign");
                log.info("调用金舜达开放API响应原始sign：{}", sign);
                boolean verify = SIGNATURE_HANDLER.verify(JSONObject.parseObject(data), sign, platform_common);
                if (!verify) {
                    // todo 验签不通过
                    log.info("调用金舜达开放API响应验签不通过：{}", sign);
                    throw new RuntimeException("验签失败");
                }
            }
        }

        return jsonObject;
    }
}
